﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.IO;

namespace EveLogMonitor
{
    public delegate void MatchFoundEventHandler(object sender, MatchFoundEventArgs e);

    public class MatchFoundEventArgs : EventArgs
    {
        public MatchFoundEventArgs(string filter)
            : base()
        {
            MatchedFilter = filter;
        }
        public string MatchedFilter { get; set; }
    }

    abstract class FileMonitor
    {
        private long filePosition = 0;

        public String FilePath { get; private set; }

        protected Timer timer;

        public event MatchFoundEventHandler Matched;

        public List<String> filterStrings;

        protected bool Started { get; set; }

        public FileMonitor(String filePath, List<String> filterStrings)
        {
            this.filterStrings = new List<String>();
            this.filterStrings.AddRange(filterStrings);
            this.FilePath = filePath;
        }

        public void CheckFile()
        {
            StreamReader file = new StreamReader(new FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
            Stream fileStream = file.BaseStream;
            fileStream.Seek(filePosition, SeekOrigin.Begin);
            String line = null;
            while ((line = file.ReadLine()) != null)
            {
                foreach (String filterString in filterStrings)
                {
                    if (Matches(line, filterString))
                    {
                        //Match found
                        if (Matched != null)
                            Matched(this, new MatchFoundEventArgs(filterString));
                    }
                }
            }
            filePosition = fileStream.Position;
        }

        internal abstract bool Matches(string line, string filter);

        public void Start(int period)

        {
            if (Started)            
            {
                //If the monitor has been started, stop it and restart it
                Stop();
            }
            // Create timer to execute now and check every period seconds
            timer = new Timer(x=>CheckFile(), null, 0, period*1000);
        }

        public void Stop()
        {
            timer.Dispose();
        }
    }
}
